package com.link_with_health.controller;

import com.alibaba.fastjson.JSONObject;
import com.link_with_health.common.Page;
import com.link_with_health.common.Result;
import com.link_with_health.common.TokenMap;
import com.link_with_health.common.VerifyUserUtil;
import com.link_with_health.exception.NullQueryResultException;
import com.link_with_health.mapper.PatientMapper;
import com.link_with_health.model.AdminLogEntity;
import com.link_with_health.model.AdminUserEntity;
import com.link_with_health.model.BatchModel;
import com.link_with_health.model.PatientEntity;
import com.link_with_health.model.UserEntity;
import com.link_with_health.service.AdminLogService;
import com.link_with_health.service.BatchOperationService;
import com.link_with_health.service.PatientService;
import com.link_with_health.service.UserService;
import com.link_with_health.utils.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.util.Map;
import java.util.List;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.HashMap;

@Controller
@RequestMapping("/api/patient")
public class PatientController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final String AUTH_TOKEN = "Authorization";
    private TokenMap tokenMap = TokenMap.getInstance();

    @Resource(name = "patientService")
    PatientService patientService;
    @Resource(name = "batchOperationService")
    BatchOperationService batchOperationService;
    @Resource(name = "userService")
    UserService userService;
    @Resource(name = "adminLogService")
    AdminLogService adminLogService;

    /**
     * 获取患者信息
     * @param json json{method : '', params: {} }
     * @param request 请求
     * @return 返回查询结果
     */
    @PostMapping("/findPatientInfo")
    @ResponseBody
    public Result findPatientInfo(@RequestBody JSONObject json
            , HttpServletRequest request){

        String token = request.getHeader(AUTH_TOKEN);
        String msg = "验签验证失败";

        if(token==null|| !tokenMap.containsKey(token)){
            logger.error("[get patient info failed]");
            return Result.fail(msg);

        }
        try {

            String method = json.getString("method");
            String paramsStr = json.getJSONObject("params").toJSONString();

            HashMap<String, Object> params = JsonUtil.json2obj(paramsStr
                    , HashMap.class);

            return method(method,params);

        } catch (Exception e){
            logger.error("[get patient info failed]",e);
            msg = "查找失败";
            if(e instanceof NullQueryResultException){
                return Result.notResult("无查找结果",null);
            }

        }

        return Result.fail(msg);
    }


    /**
     * 修改患者信息
     * @param json 患者信息 -json
     * @param request 请求
     * @return 返回操作结果
     */
    @PostMapping("/modifyPatientInfo")
    @ResponseBody
    public Result modifyPatientInfo(@RequestBody JSONObject json
            , HttpServletRequest request){

        String token = request.getHeader(AUTH_TOKEN);
        String msg = "验签验证失败";

        if(token==null|| !tokenMap.containsKey(token)){
            logger.error("[get patient info failed]");
            return Result.fail(msg);
        }
        Integer adminId = Math.toIntExact(tokenMap.get(token)
                instanceof AdminUserEntity
                ? ((AdminUserEntity) tokenMap.get(token)).getAdminID()
                : ((UserEntity) tokenMap.get(token)).getUserId());


        try {

            PatientEntity entity = JsonUtil
                    .json2obj(json.toJSONString(), PatientEntity.class);

            PatientEntity oldEntity = patientService
                    .getPatientByPatientId(entity.getPatientId());

            patientService.changePatient(entity);

            entity = patientService
                    .getPatientByPatientId(entity.getPatientId());

            //备份记录
            String object = JsonUtil.obj2json(oldEntity);
            AdminLogEntity log = new AdminLogEntity(0L, adminId
                    , "修改", "patient", object);
            adminLogService.addAdminLog(log);

            return Result.success("操作成功",entity);


        } catch (Exception e){
            logger.error("[modify failed]",e);
            msg = "操作失败";
            if(e instanceof NullQueryResultException){
                return Result.fail("绑定非法用户id");
            }
        }

        return Result.fail(msg);
    }

    /**
     * 添加患者信息
     * @param json 患者信息 -json
     * @param request 请求
     * @return 返回操作提示
     */
    @PostMapping("/addPatientInfo")
    @ResponseBody
    public Result addPatientInfo(@RequestBody JSONObject json
            , HttpServletRequest request){

        String token = request.getHeader(AUTH_TOKEN);
        String msg = "验签验证失败";

        if(token==null|| !tokenMap.containsKey(token)){
            logger.error("[get patient info failed]");
            return Result.fail(msg);
        }
        Integer adminId = Math.toIntExact(tokenMap.get(token)
                instanceof AdminUserEntity
                ? ((AdminUserEntity) tokenMap.get(token)).getAdminID()
                : ((UserEntity) tokenMap.get(token)).getUserId());


        try {

            PatientEntity entity = JsonUtil
                    .json2obj(json.toJSONString(),PatientEntity.class);

            patientService.addPatient(entity);
            entity = patientService.getPatientByPatientId(
                    entity.getPatientId());

            //备份
            String object = JsonUtil.obj2json(entity);
            AdminLogEntity log = new AdminLogEntity(0L, adminId
                    , "增加", "patient", object);
            adminLogService.addAdminLog(log);

            return Result.success("成功修改",entity);

        } catch (Exception e){
            logger.error("[add patient failed]");
            msg = "操作失败 请检查输入的参数";
            if(e instanceof NullQueryResultException){
                return Result.fail("绑定非法用户id");
            }
        }

        return Result.fail(msg);
    }

    /**
     * 删除患者信息
     * @param json ids 患者id
     * @param request
     * @return
     */
    @RequestMapping("/deletePatientInfo")
    @ResponseBody
    public Result deletePatientInfo(@RequestBody JSONObject json
            , HttpServletRequest request){
        String token = request.getHeader(AUTH_TOKEN);
        String msg = "验签验证失败";

        if(token==null|| !tokenMap.containsKey(token)){
            logger.error("[get patient info failed]");
            return Result.fail(msg);
        }


        Integer adminId = Math.toIntExact(tokenMap.get(token)
                instanceof AdminUserEntity
                ? ((AdminUserEntity) tokenMap.get(token)).getAdminID()
                : ((UserEntity) tokenMap.get(token)).getUserId());

        try{
            Long[] ids = json.getObject("ids",Long[].class);
            //备份
            StringBuilder oldEntity = new StringBuilder();
            for(Long idBk : ids){
                PatientEntity entity = patientService
                        .getPatientByPatientId(idBk);
                oldEntity.append("\n").append(JsonUtil.obj2json(entity));
            }


            List<BatchModel> models = new ArrayList<>(ids.length);

            int index = 0;
            String sql = "t.real_name= 'null', t.birthday= null " +
                    ", t.sex= '@' , t.height= 0, t.weight= 0" +
                    ", t.operation_history= null " +
                    ", user_bind= 100000, t.clinical_history= null " +
                    ", t.allergy= null ";
            for(;index < ids.length; index++){
                BatchModel model = new BatchModel("patient","",""
                        ,"patient_id",ids[index].toString(),sql);
                models.add(model);
            }

            batchOperationService.batchUpdateLikeDelete(models);

            //记录
            AdminLogEntity log = new AdminLogEntity(0L, adminId
                    , "删除","patient", oldEntity.toString());
            adminLogService.addAdminLog(log);

            return Result.success("操作成功");

        } catch(Exception e){
            logger.error("delete failed",e);
            msg = "删除失败";
        }

        return Result.fail(msg);
    }

    /**
     * 获取患者信息
     * @param json
     * @param request
     * @return
     */
    @PostMapping("/selectPatientById")
    @ResponseBody
    public Result selectPatientById(@RequestBody JSONObject json
            , HttpServletRequest request){
        String token = request.getHeader(AUTH_TOKEN);
        String msg = "验签验证失败";
        if(token==null|| !tokenMap.containsKey(token)){
            logger.error("[get patient info failed]");
            return Result.fail(msg);
        }

        try {
            Long patientId = json.getLong("patientId");
            PatientEntity patient = patientService
                    .getPatientByPatientId(patientId);

            return Result.success(patient);

        } catch (Exception e){
            logger.error("[failed to get patient by id]",e);
            msg = "获取患者信息失败";
        }

        return Result.fail(msg);
    }

    /**
     * 通过用户id信息
     * @param json userId - 患者信息
     * @param request 请求
     * @return 患者信息
     */
    @PostMapping("/selectPatientByUser")
    @ResponseBody
    public Result selectPatientByUser(@RequestBody JSONObject json
            , HttpServletRequest request) {
        String token = request.getHeader(AUTH_TOKEN);
        String msg = "验签验证失败";
        if (token == null || !tokenMap.containsKey(token)) {
            logger.error("[get patient info failed]");
            return Result.fail(msg);
        }

        try {
            Long userId = json.getLong("userId");
            List<PatientEntity> patients = patientService
                    .getPatientByUserId(userId);

            return Result.success(patients);

        } catch (Exception e) {
            logger.error("[failed to get patient by id]", e);
            msg = "获取患者信息失败";
        }
        return Result.fail(msg);
    }

    /**
     * 获取当前用户绑定的患者信息
     * @param request 请求
     * @return 患者数据
     */
    @GetMapping("/accessPatientInfo")
    @ResponseBody
    public Result accessPatientInfo(HttpServletRequest request){
        String msg = "验签失败";
        String token = request.getHeader(AUTH_TOKEN);
        if(token == null || !tokenMap.containsKey(token)){
            logger.error("[failed to get patient by token]");
            return Result.fail(msg);
        }
        try{
            Long userId  = ((UserEntity) tokenMap.get(token))
                    .getUserId();
            List<PatientEntity> patients = patientService
                    .getPatientByUserId(userId);

            //将绑定了用户100000的数据筛查掉
            patients = patientFilter(patients);

            if(patients.isEmpty())
                throw new NullQueryResultException("NULL DATA");

            return Result.success(patients);
        } catch (Exception e){
            msg = "获取患者信息失败";
            logger.error("[failed to get patient info]",e);
            if(e instanceof NullQueryResultException){
                return Result.notResult("该用户无患者信息","null");

            }

        }
        return Result.fail(msg);
    }

    /**
     * 编辑患者信息
     * @param json 接收 患者信息对象
     * @param request 请求
     * @return 返回新的患者信息
     */
    @PostMapping("/editPatientInfo")
    @ResponseBody
    public Result editPatientInfo(@RequestBody JSONObject json
            , HttpServletRequest request){
        String msg = "验签失败";
        String token = request.getHeader(AUTH_TOKEN);
        if(token == null || !tokenMap.containsKey(token)){
            logger.error("failed to edit patient by token");
            return Result.fail(msg);
        }

        try{
            Long userId = ((UserEntity) tokenMap.get(token))
                    .getUserId();

            PatientEntity entity = JsonUtil.json2obj(json.toJSONString()
                    , PatientEntity.class);

            if(userId.equals(entity.getUserBind())){

                //跟新数据
                patientService.changePatient(entity);
                entity = patientService
                        .getPatientByPatientId(entity.getPatientId());

                return Result.success(entity);
            }
            msg = "当前修改的患者信息非本用户";

        }catch(Exception e){
            logger.error("failed to edit patient",e);
            msg = "修改失败";
        }

        return Result.fail(msg);
    }


    /**
     * 通过条件查询数据
     * @param method 方法
     * @param params 参数
     * @return 结果
     * @throws Exception 异常
     */
    private Result method(String method, Map<String,Object> params)
            throws Exception{
        List<PatientEntity> list = new ArrayList<>();

        switch(method){
            case "all": case "all-page":{
                list = patientService.getAllPatient();
                list = patientFilter(list);
            }
            break;

            case "name-page":{
                String name = (String) params.get("name");
                list = patientService.getPatientByRealName(name);
                //过滤患者信息
                list = patientFilter(list);
            }
            break;

            default:
                logger.error("unknown method=>" + method);
                return Result.fail("未知查找方法");
        }

        if(list == null || list.isEmpty())
            throw new NullQueryResultException("[not result fo patient]");

        //封装 带页数数据
        if(method.contains("page")){
            Integer current = Integer.valueOf(String.valueOf(params.get("current"))) ;
            Integer size = Integer.valueOf(String.valueOf(params.get("size")));
            Page<PatientEntity> page = new Page<>(list,size,current);
            return Result.success(page.getPageDate());
        }


        return Result.success(list);

    }


    /**
     * 过滤绑定100000 的患者信息
     * @param list
     * @return
     */
    private List<PatientEntity> patientFilter(List<PatientEntity> list){
        return list.stream()
                .filter(item ->(100000 !=  item.getUserBind()))
                .collect(Collectors.toList());
    }

}
